Using Function.prototype.bind
and arrows functions as attributes will negatively impact performance in React. Each time the parent is
rendered, the function will be re-created and trigger a render of the component causing excessive renders and more memory use. Wrapping the function
in a useCallback
hook will avoid additional renders. This rule ignores Refs
. This rule does not raise findings on DOM nodes
since that may require wrapping the DOM in a component. Still, better performance can be achieved if this rule is respected in DOM nodes too.
Noncompliant code example
<Component onClick={this._handleClick.bind(this)}></Component>
<Component onClick={() => handleClick()}></Component>
Compliant solution
function handleClick() {
//...
}
<Component onClick={handleClick}></Component>
Situation can become more complicated when you need to pass additional parameters to the handler. Consider following component printing the list of
letters. Consider following non-compliant example
class Alphabet extends React.Component {
handleClick(letter) {
console.log(`clicked ${letter}`);
}
render() {
return (<div><ul>
{letters.map(letter =>
<li key={letter} onClick={() => this.handleClick(letter)}>{letter}</li>
)}
</ul></div>)
}
}
To avoid creating the arrow function you can factor out li
element as separate child component and use props
to pass the
letter
and onClick
handler.
class Alphabet extends React.Component {
handleClick(letter) {
console.log(`clicked ${letter}`);
}
render() {
return (<div><ul>
{letters.map(letter =>
<Letter key={letter} letter={letter} handleClick={this.handleClick}></Letter>
)}
</ul></div>)
}
}
class Letter extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
this.props.handleClick(this.props.letter);
}
render() {
return <li onClick={this.handleClick}> {this.props.letter} </li>
}
}
alternatively you could rewrite Letter
as a function and use useCallback
function Letter({ handleClick, letter }) {
const onClick = React.useCallback(() => handleClick(letter), [letter])
return <li onClick={onClick}>{letter}</li>
}